package com.uxsino.simo.networkentity;

import java.util.HashMap;
import java.util.Map;

import org.bouncycastle.util.Strings;

import com.alibaba.fastjson.annotation.JSONField;
import com.fasterxml.jackson.annotation.JsonAnyGetter;
import com.fasterxml.jackson.annotation.JsonAnySetter;
import com.fasterxml.jackson.annotation.JsonIgnore;
import com.fasterxml.jackson.annotation.JsonProperty;
import com.uxsino.commons.logicSelector.Prop;
import com.uxsino.commons.logicSelector.PropProxy;
import com.uxsino.reactorq.model.SOURCE_TYPE;
import com.uxsino.simo.connections.target.AbstractTarget;
import com.uxsino.simo.query.ProtocolManager;

public class EntityInfo {

    @Prop(name = "id")
    public String id;

    @JsonIgnore
    public String collectorId;

    @JsonIgnore
    private EntityClass neClass;

    @Prop(name = "class_id")
    @JsonProperty("class_id")
    @JSONField(name = "class_id")
    public String getEntityClassId() {
        return neClass == null ? null : neClass.id;
    }

    @JsonProperty("version")
    @JSONField(name = "version")
    public String version;

    @JsonProperty("releaseTime")
    @JSONField(name = "releaseTime")
    public long releaseTime;

    @JsonIgnore
    @Prop(name = "class")
    public EntityClass getEntityClass() {
        return neClass;
    }

    /**
     * The flag for simulation states.
     * 0x01: record raw query return
     * 0x02: record raw query return as well as extracted indicator value
     * 0x04: simulate query with raw query return
     * 0x08: simulate with extracted value only
     * The two higher bits CANNOT be set simultaneously
     * @see {@link SimulationManager}
     */
    @Prop(name = "simulationState")
    @JsonProperty("simulationState")
    @JSONField(name = "simulationState")
    public byte simulationState = 0x01;

    public Map<String, String> protocols;

    @JsonIgnore
    @JSONField(serialize = false)
    private Map<String, String> properties;

    public EntityInfo() {
        properties = new HashMap<>();
    }

    

    public SOURCE_TYPE sourceType = SOURCE_TYPE.PUBLIC;

    @Prop(name = "protocols")
    public AbstractTarget getTargetOfProtocol(String protocol) {
        String targetJson = protocols.get(protocol);
        if(targetJson == null){
            targetJson = protocols.get(Strings.toLowerCase(protocol));
        }
        if (targetJson == null) {
            return null;
        }
        return ProtocolManager.createTargetFromJson(targetJson, protocol);
    }

    public EntityInfo(EntityClass ne_class) {
        this.neClass = ne_class;
        protocols = new HashMap<String, String>();
    }

    public void addProtocol(String protcolName, String targetParams) {
        protocols.put(protcolName.toLowerCase(), targetParams);
    }

    @Override
    public final int hashCode() {
        return id.hashCode();
    }

    @Override
    public final boolean equals(Object obj) {
        if (this == obj) {
            return true;
        }
        if (obj == null || !(obj instanceof EntityInfo)) {
            return false;
        }
        return this.id.equals(((EntityInfo) obj).id);
    }

    public void setEntityClass(EntityClass cls) {
        this.neClass = cls;
    }

    @JsonAnyGetter
    private Map<String, String> getProperties() {
        return properties;
    }

    @PropProxy
    public String getProperty(String propName) {
        return properties.get(propName);
    }

    @JsonAnySetter
    public void setProperty(String propName, String value) {
        if (properties == null) {
            properties = new HashMap<>();
        }

        properties.put(propName, value);

    }

}
